package main

import (
	"fmt"
	"log"
	"path/filepath"
	"reflect"
	_ "reflect"
	"runtime"
	"strings"
)

type MyStruct struct {
}

func (m *MyStruct) foo(p string) {
	func(){
		fmt.Println("aa")
		ENTRY("aa")
		func(){
			fmt.Println("bb")
			ENTRY("bb")
		}()
	}()
	func(){
		fmt.Println("aac")
		ENTRY("aac")
		func(){
			fmt.Println("bbc")
			ENTRY("bcc")
		}()
	}()
	ENTRY("")
	ENTRY("Param p=%s", p)
	DEBUG("Test %s %s", "Hello", "World")

	fmt.Println("aaaaa"[0:2])
}

func DEBUG(formating string, args ... interface{}) {
	LOG("DEBUG", formating, args...)
}

func ENTRY(formating string, args ... interface{}) {
	LOG("ENTRY", formating, args...)
}

func LOG(level string, formating string, args ... interface{}) {
	filename, line, funcname := "???", 0, "???"
	pc, filename, line, ok := runtime.Caller(2)
	fmt.Println(reflect.TypeOf(pc), reflect.ValueOf(pc))
	fmt.Println(pc, filename, line)
	if ok {
		funcname = runtime.FuncForPC(pc).Name()      // main.(*MyStruct).foo
		fmt.Println("1", funcname)
		funcname = filepath.Ext(funcname)            // .foo
		fmt.Println("2", funcname)
		funcname = strings.TrimPrefix(funcname, ".") // foo
		fmt.Println("3", funcname)

		filename = filepath.Base(filename) // /full/path/basename.go => basename.go
	}

	log.Printf("%s:%d:%s: %s: %s\n", filename, line, funcname, level, fmt.Sprintf(formating, args...))
}

func main() {
	//ss := MyStruct{}
	//ss.foo("helloworld")
	fmt.Println(strings.TrimPrefix("haah.abc.aa.hh","h"))
}
